import { ListViewDelegate } from "../tools/TypeDefine";
import CCNodePool from "../pool/CCNodePool";
export default class ListView {
    private pool: CCNodePool;
    private scrollView: cc.ScrollView;
    private totalCount: number;
    private spacing: number;
    private content: cc.Node;
    private items: Array<any>;
    private lastContentPos: number;
    private delegate: ListViewDelegate;
    private delegateUpdate: Function;
    private contentSize: number;
    private position_back: number = 0;
    private position_front: number = 0;
    private offset: number;
    private itemSize:number = 0;
    private bufferZone: number;
    constructor(delegate: ListViewDelegate, pool: CCNodePool, scrollView: cc.ScrollView, totalCount: number, spacing: number = 5) {
        this.delegate = delegate;
        this.scrollView = scrollView;
        this.pool = pool;
        this.content = this.scrollView.content;
        this.scrollView.node.on('scrolling', this.updateItem, this);
        this.spacing = spacing;
        this.items = [];
        // cc.log(' totalCount ',totalCount,' poolName ',pool.getName())
        this.init(totalCount);
    }
    destroy(){
        if (this.items && this.items.length > 0) {
            this.items.forEach(element => {
                this.pool.put(element);
            });
        }
        this.items.length = 0;
    }
    // 重置
    reset(totalCount: number) {
        this.scrollView.stopAutoScroll();
        //没有用到对象池，所以当内容比之前少的时候需要移除，所以就直接移除了。
        this.destroy();
        this.init(totalCount);
        if (this.scrollView.vertical) {
            this.scrollView.scrollToTop();
        } else {
            this.scrollView.scrollToLeft();
        }
    }

    setDelegateUpdate(_delegateUpdate) {
        this.delegateUpdate = _delegateUpdate;
    }
    // 更新内容
    updateItems() {
        if (this.delegateUpdate) {
            for (let index = 0; index < this.items.length; index++) {
                let element = this.items[index];
                this.delegateUpdate(element);
            }
        }
    }
    getItemSize(){
        return this.itemSize
    }    
    private init(totalCount: number) {
        this.totalCount = totalCount;      
        let bufferSize = 0;// 
        this.position_back = -1;
        this.position_front = 0;
        let temp = this.pool.get();


        this.itemSize = 0;
        if (this.scrollView.vertical) {
            this.itemSize = (temp.height + this.spacing);
            bufferSize = this.scrollView.node.height;
        } else {
            this.itemSize = (temp.width + this.spacing);
            bufferSize = this.scrollView.node.width;
        }
        this.pool.put(temp)
        bufferSize += this.itemSize;// 多生成一个用于平滑显示。
        this.contentSize = this.totalCount * this.itemSize + this.spacing;
        let spawnCount = bufferSize % this.itemSize == 0 ? bufferSize / this.itemSize : Math.floor(bufferSize / this.itemSize) + 1;
        if (spawnCount > this.totalCount) {
            spawnCount = this.totalCount;
        }
        if (this.scrollView.vertical) {
            this.content.height = this.contentSize;
        } else {
            this.content.width = this.contentSize;
        }
        this.scrollView.scrollTo(cc.v2(0, 1), 0);
        for (let index = 0; index < spawnCount; index++) {
            this.position_back++;
            let item: cc.Node =  this.pool.get();
            if (!item) {
                continue;
            }            
            this.addChild(item);
            this.delegate(this, this.position_back,item);
            if (this.scrollView.vertical) {
                let posy = -item.height * (0.5 + index) - this.spacing * (index + 1);
                item.setPosition(0, posy);
            } else {
                let posx = item.width * (0.5 + index) + this.spacing * (index + 1);
                item.setPosition(posx, 0);
            }
            this.items.push(item);         
        }
        this.offset = this.itemSize * this.items.length;
        this.bufferZone = bufferSize / 2;
    }
    addChild(item) {
        if (!item.parent) {
            this.content.addChild(item);
        }
    }
    getPositionInView(item) { // get item position in scrollview's node space
        let worldPos = item.parent.convertToWorldSpaceAR(item.position);
        let viewPos = this.scrollView.node.convertToNodeSpaceAR(worldPos);
        return viewPos;
    }
    scrollToOffset(offset:cc.Vec2,time:number){
        this.scrollView.scrollToOffset(offset,time)
    }    
    private updateItem() {
        let items = this.items;
        let isDown = false;
        if (this.scrollView.vertical) {
            isDown = this.scrollView.content.y < this.lastContentPos; //   
        } else {
            isDown = this.scrollView.content.x > this.lastContentPos; //
        }
        for (let i = 0; i < items.length; i++) {
            let viewPos = this.getPositionInView(items[i]);
            if (this.scrollView.vertical) {
                if (isDown) {
                    if (viewPos.y < - this.bufferZone && items[i].y + this.offset < 0) {
                        this.position_front--;
                        this.position_back--;
                        items[i].y = items[i].y + this.offset;
                        this.delegate(this, this.position_front, items[i]);
                    }
                } else {
                    if (viewPos.y > this.bufferZone && items[i].y - this.offset > -this.contentSize) {
                        this.position_front++;
                        this.position_back++;
                        items[i].y = items[i].y - this.offset;
                        this.delegate(this, this.position_back, items[i]);
                    }
                }
            } else {
                if (isDown) {
                    if (viewPos.x > this.bufferZone && items[i].x - this.offset > 0) {
                        this.position_front--;
                        this.position_back--;
                        items[i].x = items[i].x - this.offset;
                        this.delegate(this, this.position_front, items[i]);
                    }

                } else {
                    if (viewPos.x < - this.bufferZone && items[i].x + this.offset < this.contentSize) {
                        this.position_front++;
                        this.position_back++;
                        items[i].x = items[i].x + this.offset;
                        this.delegate(this, this.position_back, items[i]);
                    }
                }
            }

        }
        if (this.scrollView.vertical) {
            this.lastContentPos = this.scrollView.content.y;
        } else {
            this.lastContentPos = this.scrollView.content.x;
        }
    }
}

